package com.gl.basis.zuul.filter;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gl.basis.auth.constants.AuthorityConstants;
import com.gl.basis.common.constant.ResultCode;
import com.gl.basis.common.pojo.CommBean;
import com.gl.basis.common.pojo.CommonResult;
import com.gl.basis.common.util.Md5Utils;
import com.gl.basis.common.util.RSAUtils;
import com.gl.basis.util.RedisUtil;
import com.gl.basis.zuul.entity.SysAppManage;
import com.gl.basis.zuul.entity.SysAppMapping;
import com.gl.basis.zuul.enums.RouteType;
import com.gl.basis.zuul.service.ISysAppManageService;
import com.gl.basis.zuul.service.ISysAppMappingService;
import com.gl.basis.zuul.util.CommonUtil;
import com.gl.basis.zuul.util.RSAUtil;
import com.gl.basis.zuul.util.RequestUtils;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class SignPostFilter extends ZuulFilter {

	
	@Autowired
	private RedisUtil redisUtil;
	@Resource
	private ISysAppManageService sysAppManageService;
	@Resource
	private ISysAppMappingService sysAppMappingService;
	@Resource
	private ObjectMapper objectMapper;

	@Override
	public boolean shouldFilter() {
		RequestContext currentContext = RequestContext.getCurrentContext();
		HttpServletRequest request = currentContext.getRequest();
        String path = request.getServletPath();
        //包含api就不转发
        if (!currentContext.sendZuulResponse() ||( StringUtils.isNotBlank(path)&& path.contains(RouteType.API.getCode()))) {
			return false;
		}
		return true;
	}

	@Override
	public String filterType() {
		return FilterConstants.POST_TYPE;
	}

	@Override
	public int filterOrder() {
		return 30;
	}
	@SuppressWarnings("unchecked")
	@Override
	public Object run() throws ZuulException {
		RequestContext currentContext = RequestContext.getCurrentContext();
		HttpServletRequest request = currentContext.getRequest();
		String requestParams = RequestUtils.getRequestParams(currentContext, request);
		CommBean reqParams = JSONObject.parseObject(requestParams, CommBean.class);
		String reqsign = reqParams.getSign();
		InputStream inputStream = currentContext.getResponseDataStream();
		if (inputStream == null) {
			return null;
		}
		byte[] buf = new byte[4096];
		int length = 0;
		StringBuilder sb = new StringBuilder();
		try {
			while ((length = inputStream.read(buf)) != -1) {
				sb.append(new String(buf, 0, length));
			}
		} catch (IOException e) {
			e.printStackTrace();
			log.error("读取流异常：{}", e.getMessage());
		}
		String result = sb.toString();
		log.info(result);
		if (StringUtils.isNotBlank(result)) {
			Map<String, String> map = JSON.parseObject(result, Map.class);
			String code = map.get(AuthorityConstants.CODE);
			if (StringUtils.isNotBlank(code) && !code.equalsIgnoreCase(ResultCode.SUCCESS.getCode())) {
				CommonResult<Object> failed = CommonResult.failed(map.get(AuthorityConstants.CODE),
						map.get(AuthorityConstants.MSG));
				currentContext.setResponseBody(JSON.toJSONString(failed));
				return null;
			}
			SysAppManage manage = sysAppManageService.findSerct(reqParams.getAppkey());
			String sign_method = reqParams.getSign_method();
			// 数据签名
			SysAppMapping mapping = sysAppMappingService
					.findAppMappingUrl(reqParams.getMethod());
			if (null != mapping && AuthorityConstants.SIGN_RSA.equalsIgnoreCase(sign_method)
					&& AuthorityConstants.SIGN_RSA.equalsIgnoreCase(mapping.getSignMethod())) {
				String body = null;
				try {
					body = Base64.getEncoder().encodeToString(RSAUtils
							.encryptByPublicKey(CommonUtil.buildWaitingForSign(map).getBytes(), manage.getPublicKey()));
					currentContext.setResponseBody(JSON.toJSONString(CommonResult.success(body)));
				} catch (Exception e) {
					e.printStackTrace();
					log.error("加密异常信息：{}；异常输出：{}", e.getMessage(), e);
					CommonResult<Object> failed = CommonResult.failed(map.get(AuthorityConstants.CODE),
							map.get(AuthorityConstants.MSG));
					currentContext.setResponseBody(JSON.toJSONString(failed));
					return null;
				}

			} else {
				currentContext.setResponseBody(JSON.toJSONString(CommonResult.success(map)));
			}
			if (null != mapping && StringUtils.isNotBlank(mapping.getIdempotents())
					&&AuthorityConstants.DEMPOTENCY_CODE.equalsIgnoreCase(mapping.getIdempotents())) {
				redisUtil.setnxAndExpire(AuthorityConstants.GATEWAY_IDEMPOTENCY+reqsign, reqsign, 300);
			}
		}

		return null;
	}

}
